/*****************************************************************************

File:   otkXSectionExample.java

Date          Build     Author        Version    Comments
30-Oct-12     P-20-16    dshah         $$1        Created
16-Jan-13     P-20-21    rkothari      $$2         Updated for command counter
01-Jul-14     P-20-55    rkothari      $$3         Updated for RefreshMdlTree & RMB duplication
20-mar-15 P-30-05 gshmelev $$4  called GetCurrentSession
09-June-16 P-30-33 rkothari $$5 Fixed for pop up command

****************************************************************************/

package com.ptc.otkjavaexamples;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcSession.*;
import com.ptc.pfc.pfcCommand.*;
import com.ptc.pfc.pfcGlobal.*;
import com.ptc.pfc.pfcModel.*;
import com.ptc.pfc.pfcModelItem.*;
import com.ptc.pfc.pfcFeature.*;
import com.ptc.pfc.pfcSolid.*;
import javax.swing.JOptionPane;
import java.io.*;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcFamily.*;
import com.ptc.pfc.pfcServer.*;
import com.ptc.pfc.pfcWindow.*;
import com.ptc.wfc.wfcSolid.*;
import com.ptc.wfc.wfcFeatureInstructions.*;
import com.ptc.pfc.pfcSelect.*;
import com.ptc.wfc.wfcSession.*;
import com.ptc.pfc.pfcUI.*;
import com.ptc.pfc.pfcExceptions.*;
import com.ptc.pfc.pfcXSection.*;
import com.ptc.pfc.pfcObject.*;
import com.ptc.pfc.pfcAssembly.*;
import com.ptc.wfc.wfcXSection.*;
import com.ptc.wfc.wfcSelect.*;
import com.ptc.wfc.wfcSolid.*;



public class otkXSectionExample extends DefaultUICommandActionListener
{
    
    public otkXSectionExample(String inMethod) 
    { 
	mMethod = inMethod; 
	mObjectAction=false; 
    }
    
    public otkXSectionExample(String inMethod,boolean inObjectAction ) 
    { 
	mMethod = inMethod; 
	mObjectAction = inObjectAction; 
    }
    
    /**********************************************************************
	Action-Object approach to create planar xsection
	Overrides onCommand method from pfcUICommandActionListener.
    **********************************************************************/
    public void OnCommand()
    {
	try
	    {
		Session session = pfcSession.GetCurrentSession ();
		WSession wSession = (WSession)(session);
		
		/*
		  NOTE 1 : If command is invoked using Object-Action way datum plane selection will be
		  extracted from selection buffer
		*/
		
		if(mObjectAction== true)
		    {
			SelectionBuffer selBuffer = wSession.GetCurrentSelectionBuffer();
			
			Selections sels = selBuffer.GetContents();
			
			int numSels=0;
			
			if(sels != null)
			    numSels = sels.getarraysize();
			
			if(numSels != 1)
			    return;
			
			ModelItem selItem = sels.get(0).GetSelItem();
			
			if(selItem.GetType() == ModelItemType.ITEM_SURFACE)
			    CreatePlanarXSection(sels.get(0));
			
			
		    }
		
		else
		    { 
			
			
			Model currModel = wSession.GetCurrentModel();
			
			ModelType mdlType = currModel.GetType();
			
			if(currModel == null)
			    {
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Not in session",null);
				return;	
			    }      
			
			else if((mdlType != ModelType.MDL_ASSEMBLY) && (mdlType != ModelType.MDL_PART))
			    {
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Invalid model type",null);
				return;
			    }
			
			else
			    {		
				
				if(mMethod.compareTo("Edit Hatching") == 0)
				    EditSectionHatching();	      
				
				else
				    CreatePlanarXSection((Selection) null); 
				
			    }
		    }
      
	    }
	
	catch (Exception e)
	    {
		System.out.println(e);
	    }
	
	
	return;
    }
    
	/**********************************************************************
	Creates planar section in four ways
		1.  Creates a planar section without quilt when input is surface or a datum plane
			This case uses pfcXSECTYPE_MODEL as cut object type

		2.  Creates a planar section with quilt when input is surface, datum plane and a quilt.
			If quilt is not selected it will include all quilts in model
			This case uses pfcXSECTYPE_QUILTS or pfcXSECTYPE_MODELQUILTS as cut object type
	
		3.  Creates a planar section with selected part when input is surface or datum plane & a part
		    This case uses pfcXSECTYPE_ONEPART

	    4.  Creates a planar section with excluded components.

	**********************************************************************/
    public void CreatePlanarXSection(Selection refSelection)
    {
	try
	    {
		Session session = pfcSession.GetCurrentSession ();	
		WSession wSession = (WSession)(session);
		Model model = wSession.GetCurrentModel();
		WSolid wSolid = (WSolid) (model);
		Integer value = new Integer(1);		
		
		if(refSelection == null)
		    {
			
			SelectionOptions refSelopts = 	pfcSelect.SelectionOptions_Create("datum,surface");
			refSelopts.SetMaxNumSels(value);
			
			//wSession.UIDisplayMessage("xsection_example_msg.txt","USER Plane Selection",null);
			
			Selections refSels = wSession.Select(refSelopts, null);
			
			refSelection = refSels.get(0);			
		    }
		
		XSecCutobjType cutObjtype = null;
		int quiltID = -1;
		intseq memberIdTable = null;	
		int planeId = refSelection.GetSelItem().GetId();
		XSectionComponents compExcl = null;
		
		Parent owner = refSelection.GetSelItem().GetDBParent();
		WSolid solidOwner = (WSolid)(owner);
		
		if(mMethod.compareTo("Planar") == 0)
		    cutObjtype = XSecCutobjType.XSECTYPE_MODEL;		  
		
		/*
		  NOTE 2: Asks user to select a quilt to use in the xsection definition 
		  If user aborts the operation, the selection ignores the quilt
		*/
		
		else if(mMethod.compareTo("Planar with quilt") == 0)
		    {
			
			try
			    {
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Quilt Selection",null);
				
				SelectionOptions quiltSelopts = pfcSelect.SelectionOptions_Create("dtmqlt");
				quiltSelopts.SetMaxNumSels(value);
				
				Selections quiltSels = wSession.Select(quiltSelopts, null);
				Selection selCutobj = quiltSels.get(0);			
				
				ComponentPath compPath = selCutobj.GetPath();
				
				if(compPath != null)
				    memberIdTable = compPath.GetComponentIds();
				
				quiltID = selCutobj.GetSelItem().GetId();
				
				cutObjtype = XSecCutobjType.XSECTYPE_QUILTS;
			    }
			catch (XToolkitUserAbort e)
			    {
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Quilt Selection aborted",null);
				cutObjtype = XSecCutobjType.XSECTYPE_MODELQUILTS;
			    }
		    }
		
		
		/*
		  NOTE 3: Asks user to select a part to use in the xsection definition 	          
		*/
		else if(mMethod.compareTo("Planar with part") == 0)
		    {
			if(wSolid.GetType() == ModelType.MDL_ASSEMBLY)			  
			    {
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Part Selection",null);
				
				SelectionOptions partSelopts = 	pfcSelect.SelectionOptions_Create("part");
				partSelopts.SetMaxNumSels(value);
				
				Selections partSels = wSession.Select(partSelopts, null);
				
				Selection selCutobj = partSels.get(0);
				
				ComponentPath compPath = selCutobj.GetPath();
				
				if(compPath != null)
				    memberIdTable = compPath.GetComponentIds();
				
				cutObjtype = XSecCutobjType.XSECTYPE_MODELQUILTS.XSECTYPE_ONEPART;
			    }
			
			else
			    cutObjtype = XSecCutobjType.XSECTYPE_MODELQUILTS.XSECTYPE_MODEL;
		    }
		
		/*
		  NOTE 4: Set selection environment to allow box selection and click OK after selecting objects
		  Then ask user to select components to exclude from xsection definition
		*/
		else if(mMethod.compareTo("Planar with excluded parts") == 0)
		    {
			ModelDescriptor descr = model.GetDescr();
			String ext = descr.GetExtension();
			
			if(ext.compareTo("asm") == 0)			  
			    {
				Integer num = new Integer(-1);
				wSession.UIDisplayMessage("xsection_example_msg.txt","USER Part Exclusion",null);
				
				SelectionEnvironmentOptions envOpts = SelectionEnvironmentOptions.create();
				
				envOpts.append(wfcSelect.SelectionEnvironmentOption_Create(SelectionEnvAttribute.SELECT_BY_BOX_ALLOWED,1));
				envOpts.append(wfcSelect.SelectionEnvironmentOption_Create(SelectionEnvAttribute.SELECT_DONE_REQUIRED,1));
				
				SelectionOptions partSelopts = (SelectionOptions)(wfcSelect.WSelectionOptions_Create("part", num, envOpts));	      
				
				Selections partSels = wSession.Select(partSelopts, null);
				
				if(partSels != null)
				    {	      
					int arrSize = partSels.getarraysize();
					ComponentPaths compPaths = ComponentPaths.create();
					
					for(int ii = 0;ii<arrSize;ii++)
					    compPaths.append(partSels.get(ii).GetPath());
					
					compExcl = wfcXSection.XSectionComponents_Create(compPaths, true);     
					
				    }
				
				cutObjtype = XSecCutobjType.XSECTYPE_MODEL;  
				
			    }
			}
		
		wSession.UIDisplayMessage("xsection_example_msg.txt","USER Section Name",null);
		
		String sectionName = wSession.UIReadStringMessage(Boolean.FALSE);
		
		/*
		  NOTE 6: Finally creates planar section with inputs received so far.
		  Keeping Flip as xtrue (i.e. Clip model in the direction of positive normal to xsection plane )
		*/
		
		solidOwner.CreatePlanarXSection(sectionName, planeId, cutObjtype, memberIdTable, quiltID, true, compExcl);
		solidOwner.RefreshMdlTree();      
	    }
		catch (Exception e)
		    {
			System.out.println(e);
		    }
    }
    
    /**********************************************************************
	Method visits all cross sections and their geometries
	Then it dumps information about hatch parameters in a file.
    **********************************************************************/
    public void GetSectionHatching(File fileName)
    {
	try
	    {	
		FileWriter file = new FileWriter(fileName);
		BufferedWriter hatchInfoFile = new BufferedWriter(file);
		
		Session session = pfcSession.GetCurrentSession ();
		WSession wSession = (WSession)(session); 
		
		Model currModel = wSession.GetCurrentModel();  
		WSolid solidOwner = (WSolid)(currModel);
		
		XSections sections	= solidOwner.ListCrossSections();
		
		for(int ii=0;ii<sections.getarraysize();ii++)
		    {//loop over XSections
			WXSection wSection = (WXSection)(sections.get(ii));
			
			hatchInfoFile.write(wSection.GetName());
			hatchInfoFile.newLine();
			
			XSectionGeometries sectionGeoms	= wSection.CollectGeometry(null);			
			
			for(int jj=0;jj<sectionGeoms.getarraysize();jj++)
			    {//loop over XSection Geometries
				XSectionHatches sectionHatches = wSection.GetCompXSectionHatches(jj,null);
				
				if(sectionHatches != null)
				    {
					hatchInfoFile.write("\tComponent[" + jj +"] ");
					
					XSectionGeometry sectionGeom = sectionGeoms.get(jj);
					
					for(int kk=0;kk<sectionGeom.GetMemberIdTable().getarraysize();kk++)
					    {//loop over member id table
						hatchInfoFile.write("AtPath(" + sectionGeom.GetMemberIdTable().get(kk));
						
						if(kk != (sectionGeom.GetMemberIdTable().getarraysize() - 1))
						    hatchInfoFile.write(",");
						else
						    hatchInfoFile.write(") ");
					    }//loop over member id table
					
					hatchInfoFile.write("{ ");
					hatchInfoFile.newLine();
					
					for(int ll=0;ll<sectionHatches.getarraysize();ll++)
					    {//loop over hatches
						XSectionHatch sectionHatch = sectionHatches.get(ll);
						
						hatchInfoFile.write("\t\t(ANGLE="+ sectionHatch.GetAngle() +",\tSPACING="+ sectionHatch.GetSpacing()+")");
						
						if(ll != (sectionHatches.getarraysize()-1))
						    {
							hatchInfoFile.write(",");
							hatchInfoFile.newLine();
						    }
						
						else
						    hatchInfoFile.newLine();
					    }//loop over hatches			
					
					hatchInfoFile.write("\t}");
					hatchInfoFile.newLine();
				    }
			    }//loop over XSection Geometries
			
			hatchInfoFile.write("END");
			hatchInfoFile.newLine();
		    }			
		//loop over XSections
		
		hatchInfoFile.close();
		
	    }
	catch (Exception e)
	    {
		System.out.println(e);
	    }
    }
    
    /**********************************************************************
	Allows user to edit hatch parameters for all cross section in the current model
	Method uses a file returned by GetSectionHatching() 
	which has information about all section hatching
	Then it asks user to edit the hatch parameters in that file.
	Finally when user changes & saves file it will read the file 
	and update the hatching for all cross sections

    **********************************************************************/
    void EditSectionHatching()
    {
	try
	    { //try
		File hatchFile = new File(".\\ListHatches.hatch" );
		
		if (!hatchFile.exists())
		    {
			hatchFile.createNewFile();
		    }			
		
		Session session = pfcSession.GetCurrentSession ();
		WSession wSession = (WSession)(session);
		
		Model currModel = wSession.GetCurrentModel(); 	      
		WSolid solidOwner = (WSolid)(currModel);
		
		
		GetSectionHatching(hatchFile);
		
		BufferedReader hatchInfoFile = new BufferedReader(new FileReader (hatchFile));
		
		boolean fileChanged = wSession.UIEditFile("ListHatches.hatch");
		
		if(fileChanged == true)
		    { //After Edit file
			
			
			String fileLine = null;
			String hatchParamline;
			int posStart,posEnd;
			String angleString;
			char endchar;
			int length;
			
			while(true)
			    {//eof while
				
				fileLine = hatchInfoFile.readLine();
				
				if(fileLine==null)
				    break;
				
				XSection editSection = solidOwner.GetCrossSection(fileLine);
				WXSection WEditsectionhatch = (WXSection)(editSection);
				
				int compIditer = -1;
				
				while(fileLine.compareTo("END")!=0)
				    {
					fileLine = hatchInfoFile.readLine();			  
					
					if(fileLine==null)
					    break;
					
					if(fileLine.compareTo("END")!=0)
					    compIditer++;
					
					XSectionHatches hatches = XSectionHatches.create();
					
					while(fileLine.compareTo("\t}")!=0 && fileLine.compareTo("END")!=0)
					    {				   
						fileLine = hatchInfoFile.readLine();					
						
						hatchParamline = fileLine;
						posStart = hatchParamline.indexOf("=");
						posEnd = hatchParamline.indexOf(",");
						angleString = hatchParamline.substring((posStart+1),posEnd);
						int Angle = Integer.parseInt(angleString);
						
						
						posStart = hatchParamline.indexOf("=",posEnd);
						posEnd = hatchParamline.indexOf(")",posEnd);
						angleString = hatchParamline.substring((posStart+1),posEnd);
						double Spacing = Double.parseDouble(angleString);
						
						double offset = 10.00;
						
						XSectionHatch hatch = wfcXSection.XSectionHatch_Create(Angle,Spacing,offset);
						hatches.append(hatch);
						
						length = fileLine.length();
						endchar = fileLine.charAt(length-1);
						
						if(endchar == ',')
						    continue;	
						else
						    fileLine = hatchInfoFile.readLine();
						
						
						
					    }
		  
					if(fileLine.compareTo("END") != 0)
					    {
						WEditsectionhatch.SetCompXSectionHatches(compIditer,null,hatches);
					    }
					
				    }	
				
				
				}//eof while			  
			
			hatchInfoFile.close();	 
			
		    }//After Edit file
	    }//try
	catch (Exception e)
	    {
		System.out.println(e);
	    }
    }
    
    
    private String mMethod;
    private boolean mObjectAction;
};

/**********************************************************************
Object-Action approach to create planar xsection

Overrides OnPopupmenuCreate() method from pfcPopupmenuListener.
When "Sel Obj Menu" is created in session it adds a button to it.
After clicking the button it gets processed through XSectionExamples::onCommand()

**********************************************************************/
class XSectionExamplesPopupMenu extends DefaultPopupmenuListener
{
    static int xsectionCommandCounter = 0;
    UICommand Command1 = null;

	public void OnPopupmenuCreate(Popupmenu Menu)
    {
	try
	    {

		Integer value = new Integer(1);
		
		/* NOTE 7: Check if popupmenu is selection object menu */
		if(Menu.GetName().compareTo("Sel Obj Menu")!= 0)	
		    return;		
		
		Session session = pfcSession.GetCurrentSession ();
		WSession wSession = (WSession)(session);
		ModelType mdlType = wSession.GetCurrentModel().GetType();
		
		String cascade = "XSectionCascade";
		String cascadeName = cascade + xsectionCommandCounter;			
		
		PopupmenuOptions cascademenuOpts = pfcUI.PopupmenuOptions_Create(cascadeName);
		cascademenuOpts.SetLabel("OTK XSection Examples");		
		cascademenuOpts.SetHelptext("Examples for OTK XSection");		
		
		Popupmenu cascadeMenu = Menu.AddMenu(cascademenuOpts);
		
		String popup = "XSectionPlanar";
		String popupName = popup + xsectionCommandCounter;				  
		PopupmenuOptions  menuOpts1 = pfcUI.PopupmenuOptions_Create(popupName);
		menuOpts1.SetLabel("Create Planar Section");		
		menuOpts1.SetHelptext("Creates a planar section with currently selected item");
		menuOpts1.SetPositionIndex(value);		
	
		if(Command1 == null)
			Command1 = wSession.UICreateCommand("OTKPopupMenuXSection", new otkXSectionExample("Planar",true) );
		
		xsectionCommandCounter++;
		
		try
		    {	  
    			cascadeMenu.AddButton(Command1,menuOpts1);
		    }
		catch (Exception e)
		    {
			System.out.println("1: " + e);
		    }

	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
	
	return;
    }
    
    XSectionExamplesPopupMenu() { }		

};






